package utils;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.LineNumberReader;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.lang.management.ManagementFactory;
import java.util.HashMap;
import java.util.Map;

import org.apache.commons.lang.StringUtils;
import org.junit.Test;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import services.SystemParamService;

import com.aton.db.Config;
import com.sun.management.OperatingSystemMXBean;

public class SystemTool2 {
	public static final Logger log=LoggerFactory.getLogger(SystemTool2.class);
	//private final static float TotalBandwidth = 1000;   //网口带宽,默认1000Mbps  
	private static float TotalBandwidth = Float.parseFloat(SystemParamService.getValueByCacheId(BizConstants.PARAM_MAP.get("NETWORK_SPEED")));
	private static String netName=SystemParamService.getValueByCacheId(BizConstants.PARAM_MAP.get("NETWORK_NAME"));
	private static String ip=SystemParamService.getValueByCacheId(BizConstants.PARAM_MAP.get("SSH_REBOOT_IP"));
	private static String user=SystemParamService.getValueByCacheId(BizConstants.PARAM_MAP.get("SSH_REBOOT_USER"));
	private static String pass=SystemParamService.getValueByCacheId(BizConstants.PARAM_MAP.get("SSH_REBOOT_PASS"));
	
	
	
	public final static String CPU = "CPU";
	public final static String DISK = "DISK";
	public final static String RAM = "RAM";
	public final static String NETWORK = "NETWORK";
	
	private static final int CPUTIME = 500;
	private static final int PERCENT = 100;
	private static final int FAULTLENGTH = 10;
	private final static String WINDOWS = "WINDOWS";
	private final static String LINUX = "LINUX";
	private final static long MB = 1024 * 1024;//数据单位MB
	 /** 
     * Purpose:采集CPU使用率 
     * @param args 
     * @return float,CPU使用率,小于1 
     */  
    private static float getLinuxCPUUsage() {  
        //log.info("开始收集cpu使用率");  
        float cpuUsage = 0;  
        long idleCpuTime1 = 0, totalCpuTime1 = 0;   //分别为系统启动后空闲的CPU时间和总的CPU时间  
        Map<String,Object> map=ShellUtil.execAndPass(ip, user, pass, "cat /proc/stat");
    	String line=(String)map.get("outPut");
    	if(StringUtils.isNotEmpty(line)){
    		String[] cpuLine=line.split("\n");
    		if(StringUtils.isNotEmpty(cpuLine[0])&&cpuLine[0].startsWith("cpu")){
    			line = cpuLine[0].trim();  
//                  //log.info(line);  
              String[] temp = line.split("\\s+");
              if(StringUtils.isNotEmpty(temp[4])){
              	idleCpuTime1 = Long.parseLong(temp[4]); 
              }
              for(String s : temp){  
                  if(StringUtils.isNotEmpty(s)&&!s.equals("cpu")){  
                      totalCpuTime1 += Long.parseLong(s);  
                  }  
              }     
    		}
    	}
        try {  
            Thread.sleep(100);  
        } catch (InterruptedException e) {  
            StringWriter sw = new StringWriter();  
            e.printStackTrace(new PrintWriter(sw));  
            log.error("CpuUsage休眠时发生InterruptedException. " + e.getMessage());  
            log.error(sw.toString());  
        }  
        //第二次采集CPU时间  
        long idleCpuTime2 = 0, totalCpuTime2 = 0;   //分别为系统启动后空闲的CPU时间和总的CPU时间  
        Map<String,Object> map2=ShellUtil.execAndPass(ip, user, pass, "cat /proc/stat");
    	line=(String)map2.get("outPut");
    	if(StringUtils.isNotEmpty(line)){
    		String[] cpuLine=line.split("\n");
    		if(StringUtils.isNotEmpty(cpuLine[0])&&cpuLine[0].startsWith("cpu")){
    			line = cpuLine[0].trim();  
              String[] temp = line.split("\\s+");
              if(StringUtils.isNotEmpty(temp[4])){
              	idleCpuTime2 = Long.parseLong(temp[4]); 
              }
              for(String s : temp){  
                  if(StringUtils.isNotEmpty(s)&&!s.equals("cpu")){  
                      totalCpuTime2 += Long.parseLong(s);  
                  }  
              }     
    		}
    	}
        if(idleCpuTime1 != 0 && totalCpuTime1 !=0 && idleCpuTime2 != 0 && totalCpuTime2 !=0){  
            cpuUsage = 1 - (float)(idleCpuTime2 - idleCpuTime1)/(float)(totalCpuTime2 - totalCpuTime1);  
        }                 
		return cpuUsage*100;
    }  
    
    /** 
     * Purpose:采集内存使用率 
     * @param args 
     * @return float,内存使用率,小于1 
     */  
    private static Map<String,Object> getLinuxMemoryUsage() { 
    	Map<String,Object> map = new HashMap<String,Object>();
       // log.info("开始收集memory使用率");  
        float memUsage = 0.0f;  
        Map<String,Object> map2=ShellUtil.execAndPass(ip, user, pass, "cat /proc/meminfo");
    	String line=(String)map2.get("outPut");
    	long totalMem = 0, freeMem = 0; 
		if (StringUtils.isNotEmpty(line)) {
			String[] cpuLine = line.split("\n");
			if(cpuLine==null||cpuLine.length<2){
				return null;
			}
			String[] memInfo = cpuLine[0].split("\\s+");
			if (memInfo[0].startsWith("MemTotal")
					&& StringUtils.isNotEmpty(memInfo[1])) {
				totalMem = Long.parseLong(memInfo[1]);
			}
			String[] memfree = cpuLine[1].split("\\s+");
			if (memfree[0].startsWith("MemFree")
					&& StringUtils.isNotEmpty(memfree[1])) {
				freeMem = Long.parseLong(memfree[1]);
			}
			
		}
		memUsage = 1 - (float) freeMem / (float) totalMem;
		map.put("memUsageRate", memUsage * 100);
		map.put("freeMem", freeMem / MB);
		map.put("memUsage", (totalMem - freeMem) / MB);// 以使用内存,单位MB
        return map;  
    }  
    
    /** 
     * @Purpose:采集磁盘IO使用率 
     * @param args 
     * @return float,磁盘IO使用率,小于1 
     */  
    private static Map<String,Object> getLinuxDiskIOUsage() {  
    	Map<String,Object> map = new HashMap<String,Object>();
       // log.info("开始收集磁盘IO使用率");  
        float ioUsage = 0.0f;  
        Map<String,Object> map2=ShellUtil.execAndPass(ip, user, pass, "iostat -d -x");
    	String line=(String)map2.get("outPut");
    	if (StringUtils.isNotEmpty(line)) {
    		String[] cpuLine = line.split("\n");
    		for(int i=0;i<cpuLine.length;i++){
    			if(i >=3){
    				String[] temp = cpuLine[i].split("\\s+");  
	                 if(temp.length > 1){  
	                     float util =0.0f;
	                    if("wsec/s4_".equals(temp[temp.length-1])||"%util".equals(temp[temp.length-1])){
	                    	continue;
	                    }
	                     if(StringUtils.isNotEmpty(temp[temp.length-1])){
	                    	 util= Float.parseFloat(temp[temp.length-1]);  
	                     }
	                     ioUsage = (ioUsage>util)?ioUsage:util;  
	                 }  
    			}
    		}
    	}
    	map.put("diskUsageRate", ioUsage);
        return map;  
    }  
    
    /** 
     * @Purpose:采集网络带宽使用率 
     * @param args 
     * @return float,网络带宽使用率,小于1 
     */  
    private static Map<String,Object> getLinuxNetUsage() { 
    	Map<String,Object> map = new HashMap<String,Object>();
       // log.info("开始收集网络带宽使用率");  
        float netUsage = 0.0f;  
        float curRate = 0.0f;
        long startTime = System.currentTimeMillis();
        Map<String,Object> map2=ShellUtil.execAndPass(ip, user, pass, "cat /proc/net/dev");
    	String line=(String)map2.get("outPut");
    	long inSize1 = 0, outSize1 = 0;
    	if (StringUtils.isNotEmpty(line)) {
    		String[] cpuLine = line.split("\n");
    		for(int i=0;i<cpuLine.length;i++){
    			if(cpuLine[i].contains(netName)){  
    				String[] datelist = cpuLine[i].split(":");
                    String[] temp = datelist[1].split("\\s+");   
//					inSize1 = Long.parseLong(temp[0].substring(5)); // Receivebytes,单位为Byte
//					outSize1 = Long.parseLong(temp[8]); // Transmitbytes,单位为Byte
                    if(StringUtils.isNotEmpty(temp[1])){
                    	inSize1 = Long.parseLong(temp[1]);
                    }
                    if(StringUtils.isNotEmpty(temp[8])){
                    	outSize1 = Long.parseLong(temp[8]);
                    }
                    break;
    			}
    		}
    		
    	}
		try {  
	         Thread.sleep(1000);  
	    } catch (InterruptedException e) {  
	         StringWriter sw = new StringWriter();  
	         e.printStackTrace(new PrintWriter(sw));  
	         log.error("NetUsage休眠时发生InterruptedException. " + e.getMessage());  
	         log.error(sw.toString());  
	    }  
		long endTime = System.currentTimeMillis();
    	Map<String,Object> map3=ShellUtil.execAndPass(ip, user, pass, "cat /proc/net/dev");
     	line=(String)map3.get("outPut");
     	long inSize2 = 0 ,outSize2 = 0;  
     	if (StringUtils.isNotEmpty(line)) {
    		String[] cpuLine = line.split("\n");
    		for(int i=0;i<cpuLine.length;i++){
    			if(cpuLine[i].contains(netName)){  
    				String[] datelist = cpuLine[i].split(":");
                    String[] temp = datelist[1].split("\\s+");  
//					inSize2 = Long.parseLong(temp[0].substring(5));
//					outSize2 = Long.parseLong(temp[8]);
                    if(StringUtils.isNotEmpty(temp[1])){
                    	inSize2 = Long.parseLong(temp[1]);
                    }
                    if(StringUtils.isNotEmpty(temp[8])){
                    	outSize2 = Long.parseLong(temp[8]);
                    }
                    break;  
    			}
    		}
     	}
            if(inSize1 != 0 && outSize1 !=0 && inSize2 != 0 && outSize2 !=0){  
                float interval = (float)(endTime - startTime)/1000;  
				// 网口传输速度,单位为kbps
				curRate = (float) (inSize2 - inSize1 + outSize2 - outSize1)*8
						/ (1024 *1024 * interval);
                netUsage = curRate/TotalBandwidth;  
				map.put("netWorkUsageRate", netUsage * 100);// 使用率
                map.put("netWorkCurRate", curRate);//带宽
				// log.info("本节点网口速度为: " + curRate + "Kbps");
              //  log.info("本节点网络带宽使用率为: " + netUsage);  
            }                 
        return map;  
    }  
    
    private static float getWindowsCPUUsage(){
    	//long start = System.currentTimeMillis();
    	try {
			String procCmd = System.getenv("windir")
					+ "\\system32\\wbem\\wmic.exe process get Caption,CommandLine,KernelModeTime,ReadOperationCount,ThreadCount,UserModeTime,WriteOperationCount";
			// 取进程信息
			long[] c0 = readCpu(Runtime.getRuntime().exec(procCmd));
			//Thread.sleep(CPUTIME);
			long[] c1 = readCpu(Runtime.getRuntime().exec(procCmd));
			if (c0 != null && c1 != null) {
				long idletime = c1[0] - c0[0];
				long busytime = c1[1] - c0[1];
				return (float) (PERCENT * (busytime) * 1.0 / (busytime + idletime));
			} else {
				return 0;
			}
		} catch (Exception ex) {
			ex.printStackTrace();
			return 0;
		}/*finally {
			System.out.println(System.currentTimeMillis() - start);
		}*/
    }
    
 // 读取cpu相关信息
 	private static long[] readCpu(final Process proc) {
 		long[] retn = new long[2];
 		try {
 			proc.getOutputStream().close();
 			InputStreamReader ir = new InputStreamReader(proc.getInputStream());
 			LineNumberReader input = new LineNumberReader(ir);
 			String line = input.readLine();
 			if (line == null || line.length() < FAULTLENGTH) {
 				return null;
 			}
 			int capidx = line.indexOf("Caption");
 			int cmdidx = line.indexOf("CommandLine");
 			int rocidx = line.indexOf("ReadOperationCount");
 			int umtidx = line.indexOf("UserModeTime");
 			int kmtidx = line.indexOf("KernelModeTime");
 			int wocidx = line.indexOf("WriteOperationCount");
 			long idletime = 0;
 			long kneltime = 0;
 			long usertime = 0;
 			while ((line = input.readLine()) != null) {
 				if (line.length() < wocidx) {
 					continue;
 				}
 				// 字段出现顺序：Caption,CommandLine,KernelModeTime,ReadOperationCount,
 				// ThreadCount,UserModeTime,WriteOperation
 				String caption = substring(line, capidx, cmdidx - 1).trim();
 				String cmd = substring(line, cmdidx, kmtidx - 1).trim();
 				if (cmd.indexOf("wmic.exe") >= 0) {
 					continue;
 				}
 				String s1 = substring(line, kmtidx, rocidx - 1).trim();
 				String s2 = substring(line, umtidx, wocidx - 1).trim();
 				if (caption.equals("System Idle Process") || caption.equals("System")) {
 					if (s1.length() > 0)
 						idletime += Long.valueOf(s1).longValue();
 					if (s2.length() > 0)
 						idletime += Long.valueOf(s2).longValue();
 					continue;
 				}
 				if (s1.length() > 0)
 					kneltime += Long.valueOf(s1).longValue();
 				if (s2.length() > 0)
 					usertime += Long.valueOf(s2).longValue();
 			}
 			retn[0] = idletime;
 			retn[1] = kneltime + usertime;
 			return retn;
 		} catch (Exception ex) {
 			ex.printStackTrace();
 		} finally {
 			try {
 				proc.getInputStream().close();
 			} catch (Exception e) {
 				e.printStackTrace();
 			}
 		}
 		return null;
 	}
 	
 	/**
	 * 由于String.subString对汉字处理存在问题（把一个汉字视为一个字节)，因此在 包含汉字的字符串时存在隐患，现调整如下：
	 * 
	 * @param src
	 *            要截取的字符串
	 * @param start_idx
	 *            开始坐标（包括该坐标)
	 * @param end_idx
	 *            截止坐标（包括该坐标）
	 * @return
	 */
	private static String substring(String src, int start_idx, int end_idx) {
		byte[] b = src.getBytes();
		String tgt = "";
		for (int i = start_idx; i <= end_idx; i++) {
			tgt += (char) b[i];
		}
		return tgt;
	}
	/**
	 * 获取内存使用率
	 * @return
	 */
	private static Map<String,Object> getWindowsMemoryUasge(){
		Map<String,Object> map = new HashMap<String,Object>();
		OperatingSystemMXBean osmxb = (OperatingSystemMXBean) ManagementFactory.getOperatingSystemMXBean();
		// 总的物理内存+虚拟内存
		long totalvirtualMemory = osmxb.getTotalPhysicalMemorySize();
		// 剩余的物理内存
		long freePhysicalMemorySize = osmxb.getFreePhysicalMemorySize(); 
		float compare = (float) (1 - freePhysicalMemorySize * 1.0 / totalvirtualMemory) * 100;
		map.put("memUsageRate", compare);
		map.put("freeMem", freePhysicalMemorySize/MB);
		map.put("memUsage", (totalvirtualMemory - freePhysicalMemorySize)/MB);//已使用内存MB
		return map;
	}
    
    public static Map<String,Object> getResourceInfoUsage(){
    	String system = System.getProperties().getProperty("os.name").toUpperCase();
    	Map<String,Object> map = new HashMap<String,Object>();
    	map.put("cpuUsageRate", getLinuxCPUUsage());
		map.putAll(getLinuxMemoryUsage());
		map.putAll(getLinuxDiskIOUsage());
		map.putAll(getLinuxNetUsage());
    	if(system.indexOf(WINDOWS)>=0){
//			map.put("cpuUsageRate", getWindowsCPUUsage());
//			map.putAll(getWindowsMemoryUasge());
//			map.put("diskUsageRate", 0);
//			map.put("netWorkUsageRate", 0);
    	}else if(system.indexOf(LINUX)>=0){
    		map.put("cpuUsageRate", getLinuxCPUUsage());
    		map.putAll(getLinuxMemoryUsage());
    		map.putAll(getLinuxDiskIOUsage());
    		map.putAll(getLinuxNetUsage());
    	}
    	return map;
    }
    
    @Test
    public void show(){
    	
//    	System.out.println("cpu:" + getLinuxCPUUsage());
//    	System.out.println("ram:" + getLinuxMemoryUsage());
//    	System.out.println("disk:" + getLinuxDiskIOUsage());
//    	System.out.println("network:" + getLinuxNetUsage());
    }
}
